//
// Created by wangjunjun on 2024/9/19.
//

#include "udpclient.h"
#include <json.h>
#include <value.h>
#include "../log/log.h"
#include "../config/configmanager.h"
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cerrno>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
std::unique_ptr<udpClient> udpClient::m_InStance = nullptr;
std::once_flag udpClient::m_Flag;
udpClient& udpClient::GetInStance() {
    std::call_once(m_Flag, []{
        m_InStance.reset(new udpClient());
    });
    return  *m_InStance;
}

udpClient::udpClient():m_serverAddress(""), m_port(1636) {
    init();
}
udpClient::~udpClient(){
    if(m_isConnected){
        close(m_socket);
    }
}
//初始化
bool  udpClient::init() {
    std::shared_ptr<CConfigManager> pIntance = CConfigManager::GetInstance();
    if (nullptr != pIntance) {
        std::string strPath = "./CFG/config";
        Json::Value tempValue = Json::Value::null;
        if (!pIntance->loadConfig(strPath, tempValue)) {
            LOG_ERROR("Loading Config error!");
            return false;
        } else {
            if (tempValue.isMember("c_address") && tempValue["c_address"].isString()){
                //将DogSn转变路径
                m_serverAddress = tempValue["c_address"].asCString();
            }
            if (tempValue.isMember("m_port") && tempValue["m_port"].isUInt()){
                //将DogSn转变路径
                m_port= tempValue["m_port"].asUInt();
            }
            createSocket();
            connectToServer();
            return true;
        }
    }
}
void udpClient::createSocket() {
    m_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if(m_socket < 0){
        LOG_ERROR("Failed to Create UDP socket :{}", strerror(errno));
    }
}

void udpClient::connectToServer() {
    sockaddr_in serverAddr;
    std::memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(m_port);
    if (inet_pton(AF_INET, m_serverAddress.c_str(), &serverAddr.sin_addr) <= 0) {
        LOG_ERROR("Invalid server address.");
        return;
    }
    if (connect(m_socket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        LOG_ERROR("Failed to connect UDP socket:{} ", strerror(errno));
    } else {
        m_isConnected = true;
    }
}
bool udpClient::SenData(const std::string& data) {
    if (m_isConnected) {
        sockaddr_in serverAddr;
        std::memset(&serverAddr, 0, sizeof(serverAddr));
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(m_port);
        inet_pton(AF_INET, m_serverAddress.c_str(), &serverAddr.sin_addr);
        if (sendto(m_socket, data.c_str(), data.size(), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
            LOG_ERROR("Failed to send datagram:{} ", strerror(errno));
            return false;
        }
        return true;
    } else {
        LOG_ERROR("UDP client is not connected.");
        return false;
    }
}